package com.ruoyi.common.utils;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * <ul>
 * <li><strong>MD5加密方法</strong> {@link #encode(String)}</li>
 * <li><strong>MD5加密方法</strong> {@link #decode(String)}</li>
 * <li><strong>字节数组转化为16进制字符串</strong> {@link #byteArrayToHex(byte[])}</li>
 * <li><strong>字节数组MD5算法</strong> {@link #byte2MD5(byte[])}</li>
 * <li><strong>文件名加密MD5</strong> {@link #getMD5ForFile(String)}</li>
 * <li><strong>字符串加密MD5</strong> {@link #getMD5Str(String)}</li>
 * </ul>
 *
 * <pre>
 *     author: Simon
 *     time  : 2018/11/11
 *     qq    : 8950764
 *     email : simon@cmonbaby.com
 *     desc  : MD5加密方法
 * </pre>
 */
public class MD5Util {
    private static final Logger log = LoggerFactory.getLogger(MD5Util.class);

    /**
     * MD5加密方法
     * @param s 传入需要加密的字符串
     * @return 返回加密好的字符串
     */
    public static String encode(String s) {
        try {
            // 获取到数字消息的摘要器
            MessageDigest digest = MessageDigest.getInstance("MD5");
            // 执行加密操作
            byte[] result = digest.digest(s.getBytes());
            StringBuilder sb = new StringBuilder();
            // 将每个byte字节的数据转换成16进制的数据
            for (int i = 0; i < result.length; i++) {
                int number = result[i] & 0xff;
                String str = Integer.toHexString(number);// 将十进制的number转换成十六进制数据
                if (str.length() == 1) {// 判断加密后的字符的长度，如果长度为1，则在该字符前面补0
                    sb.append("0");
                    sb.append(str);
                } else {
                    sb.append(str);
                }
            }
            return sb.toString();// 将加密后的字符转成字符串返回
        } catch (NoSuchAlgorithmException e) {// 加密器没有被找到，该异常不可能发生。因为我们填入的“MD5”是正确的
            log.error("程序异常", e.getMessage());
            // CNA'T REACH;
            return "";
        }
    }

    public static String decode(String s) {
        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f' };
        try {
            byte[] btInput = s.getBytes();
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }

    // 字节数组转化为16进制字符串
    public static String byteArrayToHex(byte[] byteArray) {
        char[] hexDigits = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F' };
        char[] resultCharArray =new char[byteArray.length * 2];
        int index = 0;
        for (byte b : byteArray) {
            resultCharArray[index++] = hexDigits[b>>> 4 & 0xf];
            resultCharArray[index++] = hexDigits[b & 0xf];
        }
        return new String(resultCharArray);
    }

    // 字节数组MD5算法
    public static byte[] byte2MD5(byte[] bytes) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.update(bytes);
            return messageDigest.digest();
        } catch (NoSuchAlgorithmException e) {
            log.error("程序异常", e.getMessage());
        }
        return null;
    }

    // 文件名加密MD5
    public static String getMD5ForFile(String content) {
        try {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            digest.update(content.getBytes());
            return getHashString(digest);

        } catch (NoSuchAlgorithmException e) {
            log.error("程序异常", e.getMessage());
        }
        return null;
    }

    private static String getHashString(MessageDigest digest) {
        StringBuilder builder = new StringBuilder();
        for (byte b : digest.digest()) {
            builder.append(Integer.toHexString((b >> 4) & 0xf));
            builder.append(Integer.toHexString(b & 0xf));
        }
        return builder.toString();
    }

    // 字符串加密MD5
    public static String getMD5Str(String str) {
        MessageDigest messageDigest = null;

        try {
            messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.reset();
            messageDigest.update(str.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            System.out.println("NoSuchAlgorithmException caught!");
            System.exit(-1);
        } catch (UnsupportedEncodingException e) {
            log.error("程序异常", e.getMessage());
        }

        byte[] byteArray = messageDigest.digest();
        StringBuffer md5StrBuff = new StringBuffer();
        for (int i = 0; i < byteArray.length; i++) {
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
                md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
            else
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
        }

        return md5StrBuff.toString();
    }
}